var Fw = {
    /**
     * ID Seed
     */
    IDSeed : 10000,
    /**
     * 组件初始化队列
     * onReady后，自动初始化
     */
    Queues: [],
    /**
     * 返回ID
     * @param {Object} v
     */
    id : function() {
        return 'fw-gen-' + (++Fw.IDSeed);
    },
    /**
     * 返回UUID
     * @param {int} len
     */
    uuid: function(len){
        var uuid = [], me = arguments.callee, c = me.chars;
        len = len || 32;
        if (!c) c = me.chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
        for (var i = 0; i < len; i++) uuid[i] = c[0 | Math.random() * 62];
        return uuid.join('');
    },
    /**
     * 空白函数
     */
    emptyFn : function() {
    },
    /**
     * 定义命名空间
     */
    namespace : function() {
        var space = null, path;
        Fw.each(arguments, function(v) {
            path = v.split('.');
            space = window[path[0]] = window[path[0]] || {};
            Fw.each(path.slice(1), function(v2) {
                space = space[v2] = space[v2] || {};
            });
        });
        return space;
    },
    /**
     * 属性复制（同jQuery的$.extend）
     * @param {} object
     * @param {} config
     * @param {} defaults
     */
    apply : function(object, config, defaults) {
        if (defaults) {
            Fw.apply(object, defaults);
        }
        if (object && config && Fw.isObject(config)) {
            for (var property in config) {
                object[property] = config[property];
            }
        }
        return object;
    },
    /**
     * 属性复制（仅复制object中不存在的属性）
     * @param {} object
     * @param {} config
     */
    applyIf : function(object, config) {
        if (object) {
            for (var p in config) {
                if (!Fw.isDefined(object[p])) {
                    object[p] = config[p];
                }
            }
        }
        return object;
    },
    /**
     * 继承
     */
    extend : function() {
        var objectConstructor = Object.prototype.constructor, inlineOverrides = function(o) {
            for (var m in o) {
                if (!o.hasOwnProperty(m)) {
                    continue;
                }
                this[m] = o[m];
            }
        };
        return function(subclass, superclass, overrides) {
            /*
            if(Fw.isString(subclass)){
                var className = subclass;
                if(!eval(className)){
                    seajs.async = false;
                    seajs.use(className);
                    subclass = eval(className);
                    alert(subclass);
                    return Fw.extend(subclass, superclass, overrides);
                }
            }
            */
            //
            if (Fw.isObject(superclass)) {
                overrides = superclass;
                superclass = subclass;
                subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
                    superclass.apply(this, arguments);
                };
            }
            if (!superclass) {
                return null;
            }
            //
            var F = function() {
            };
            var subclassProto, superclassProto = superclass.prototype;
            F.prototype = superclassProto;
            subclassProto = subclass.prototype = new F();
            subclassProto.constructor = subclass;
            subclass.superclass = superclassProto;
            if (superclassProto.constructor === objectConstructor) {
                superclassProto.constructor = superclass;
            }
            subclass.override = function(overrides) {
                Fw.override(subclass, overrides);
            };
            subclassProto.override = inlineOverrides;
            subclassProto.proto = subclassProto;
            subclass.override(overrides);
            subclass.extend = function(o) {
                return Fw.extend(subclass, o);
            };
            return subclass;
        };
    }(),
    /**
     * 覆盖
     * @param {} cls
     * @param {} overrides
     */
    override : function(cls, overrides) {
        Fw.apply(cls.prototype, overrides);
    },
    /**
     * 转换为字符
     * @param {Object} v
     */
    toString : function(v) {
        return Object.prototype.toString.apply(v);
    },
    /**
     * 是否已定义
     * @param {} v
     */
    isDefined : function(v) {
        return typeof v !== 'undefined';
    },
    /**
     * 是否为空
     * @param {} v
     * @param {} allowBlank
     */
    isEmpty : function(v, allowBlank) {
        if(Fw.isObject(v)){
            var name;
            for (name in v) {
                return false;
            }
            return true;
        }
        if(Fw.isArray(v)){
            return !v.length;
        }
        return v === null || v === undefined || String(v).toUpperCase() === 'NULL' || (!allowBlank ? v === '' : false);
    },
    /**
     * 是否相等
     * 支持各种类型比较
     */
    isEqual : function(value, value2){
        //都是NULL
        if(Fw.isEmpty(value) && Fw.isEmpty(value2)){
            return true;
        }
        //其中一个是NULL
        else if(Fw.isEmpty(value) || Fw.isEmpty(value2)){
            return false;
        }
        //数组
        else if (Fw.isArray(value) && Fw.isArray(value2)) {
            return value.sort().toString() === value2.sort().toString();
        }
        //日期
        else if (Fw.isDate(value) && Fw.isDate(value2)) {
            return value.getTime() === value2.getTime();
        }
        //非Object（Object只做简单比较）
        else if(!Fw.isObject(value) && !Fw.isObject(value)){
            return String(value) === String(value2);
        }
        
        //
        return value === value2;
    },
    /**
     * 是否是数组
     * @param {} v
     */
    isArray : function(v) {
        return Fw.toString(v) === '[object Array]';
    },
    /**
     * 是否是日期
     * @param {} v
     */
    isDate : function(v) {
        return Fw.toString(v) === '[object Date]' && String(v) !== 'Invalid Date';
    },
    /**
     * 是否是对象
     * @param {} v
     */
    isObject : function(v) {
        return !!v && Fw.toString(v) === '[object Object]' && !Fw.isNumber(v.length) && !Fw.isFunction(v.splice) && (!Fw.isFunction(v.propertyIsEnumerable) || !v.propertyIsEnumerable('splice'));
    },
    /**
     * 是否是函数
     * @param {} v
     */
    isFunction : function(v) {
        return Fw.toString(v) === '[object Function]';
    },
    /**
     * 是否是数值型
     * @param {} v
     */
    isNumber : function(v) {
        return typeof v === 'number' && isFinite(v);
    },
    /**
     * 是否是字符型
     * @param {} v
     */
    isString : function(v) {
        return typeof v === 'string';
    },
    /**
     * 是否是布尔型
     * @param {} v
     */
    isBoolean : function(v) {
        return typeof v === 'boolean';
    },
    /**
     * 是否是原始类型
     * @param {} v
     */
    isPrimitive : function(v) {
        return Fw.isString(v) || Fw.isNumber(v) || Fw.isBoolean(v);
    },
    /**
     * 是否可迭代
     * @param {} v
     */
    isIterable : function(v) {
        return (v && typeof v !== 'string') ? Fw.isDefined(v.length) : false;
    },
    /**
     * 是否是URL
     * @param {} v
     * @return {}
     */
    isURL : function(v) {
        return Fw.util.VTypes.url(v);
    },
    /**
     * 滚动距离
     */
    getScrollTop: function(){
        var bodyScrollTop = 0, documentScrollTop = 0;
        if(document.body){
            bodyScrollTop = document.body.scrollTop;
        }
        if(document.documentElement){
            documentScrollTop = document.documentElement.scrollTop;
        }
        return (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;
    },
    /**
     * 文档高度
     */
    getScrollHeight: function(){
        var bodyScrollHeight = 0, documentScrollHeight = 0;
        if(document.body){
            bodyScrollHeight = document.body.scrollHeight;
        }
        if(document.documentElement){
            documentScrollHeight = document.documentElement.scrollHeight;
        }
        return (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight;
    },
    /**
     * 浏览器高度
     */
    getWindowHeight: function(){
        if(document.compatMode == 'CSS1Compat'){
            return document.documentElement.clientHeight;
        }
        else{
            return document.body.clientHeight;
        }
    },
    /**
     * 页面跳转
     * @param {} url
     * @param {} params
     * @param {} local（如果是向后抬提交请求，则应设置为false）
     */
    redirect : function(url, params, local) {
        if (Fw.isEmpty(params)) {
            params = {};
        }
        var ps = encodeURIComponent(Fw.encode(params));
        //本地存储
        if(local !== false){
            Fw.util.Storage.set('_parameters', ps);
        }
        //在url中存储（一般用于提交到后台）
        else{
            var search = document.location.search;
            if (!Fw.isEmpty(search)) {
                search = search.replace(/(&?)t=[^&]+/g, '');
                search = search.replace(/(&?)parameters=[^&]+/g, '');
                url += search === '?' ? '' : search;
            }
            url += (url.indexOf('?') > 0 ? '&' : '?') + 'parameters=' + ps;
        }
        
        //记录跳转层次（累计）
        // var level = Fw.util.Storage.get('_HISTORY_LEVEL') || 0;
        // Fw.util.Storage.set('_HISTORY_LEVEL', level === 0 ? 1 : ++level);
        
        //跳转
        url += (url.indexOf('?') > 0 ? '&' : '?') + 't=' + new Date().getTime();
        document.location.href = url;
    },
    /**
     * 返回parameters参数
     * 特指页面跳转间传递的参数
     */
    getParameters : function(key) {
        if(key){
            return Fw.getParameters() ? Fw._parameters[key] : Fw.getParameter(key) || null;
        }
        else{
            if (Fw._parameters) {
                return Fw._parameters;
            }
            else{
                var ps1 = Fw.util.Storage.get('_parameters') || Fw.getParameter('parameters');
                ps1 = Fw.isEmpty(ps1) ? {} : Fw.decode(decodeURIComponent(ps1));
                var ps2 = Fw.getParameter();
                if(!Fw.isEmpty(ps2)){
                    Fw.apply(ps1, ps2);
                }
                Fw._parameters = Fw.isEmpty(ps1) ? null : ps1;
                return Fw._parameters;
            }
        }
    },
    /**
     * 遍历数组
     * @param {} value
     * @param {} fn
     * @param {} scope
     */
    each : function(value, fn, scope) {
        if (Fw.isEmpty(value)) {
            return;
        }
        if (!Fw.isDefined(scope)) {
            scope = value;
        }
        if (Fw.isObject(value)) {
            var i = 0;
            for (var prop in value) {
                if (value.hasOwnProperty(prop)) {
                    if (fn.call(scope || value, prop, value[prop], i++, value) === false) {
                        return;
                    };
                }
            }
        } else {
            if (!Fw.isIterable(value) || Fw.isPrimitive(value)) {
                value = [value];
            }
            for (var i = 0, len = value.length; i < len; i++) {
                if (fn.call(scope || value[i], value[i], i, value) === false) {
                    return i;
                }
            }
        }
    },
    /**
     * 绑定作用域
     * @param {} fn
     * @param {} scope
     * @param {} args
     * @return {}
     */
    bind : function(fn, scope, args, appendArgs) {
        if (!Fw.isFunction(fn)) {
            return fn;
        }
        if(args){
            var method = fn, slice = Array.prototype.slice;
            return function() {
                var callArgs = args || arguments;
                if (appendArgs === true) {
                    callArgs = slice.call(arguments, 0);
                    callArgs = callArgs.concat(args);
                }
                return method.apply(scope, callArgs);
            };
        }
        else{
            return function() {
                return fn.apply(scope, arguments);
            };
        }
    },
    /**
     * 触发回调函数 
     * @param {} fn
     * @param {} scope
     * @param {} args
     */
    call: function(fn, scope, args){
        if(!fn){
            return fn;
        }
        else if(Fw.isArray(fn)){
            Fw.each(fn, function(cb){
                if(Fw.call(cb, scope, args) === false){
                    return false;
                }
            });
            return;//无返回值
        }
        else if(Fw.isFunction(fn)){
            if(scope){
                if(args){
                    return fn.apply(scope, args);
                }
                else{
                    return fn.call(scope);
                }
            }
            else{
                return Fw.call(fn, fn, args);
            }
        }
        else if(Fw.isObject(fn) && fn.fn){
            return Fw.call(fn.fn, scope || fn.scope, args || fn.args);
        }
        else{
            return fn;
        }
    },
    /**
     * 延时执行 
     */
    defer: function(fn, delay, scope, args, appendArgs) {
        fn = Fw.bind(fn, scope, args, appendArgs);
        if (delay > 0) {
            return setTimeout(fn, delay);
        }
        fn();
        return 0;
    },
    /**
     * 页面加载完毕后，初始化应用
     * @param {} app
     */
    onReady : function(app) {
        var deps = Fw.isArray(app.requires) ? app.requires : [];
        var uri = seajs.Module.resolve(Fw.appPath);
        if (Fw.isFunction(app.init)) {
            deps = deps.concat(seajs.parseDependencies(app.init.toString()));
            seajs.use(deps, function(){
                // var callback = function(){
                    //初始化队列
                    Fw.call(Fw.Queues);
                    delete Fw.Queues;
                    //初始化业务功能
                    Fw.Logger.debug('初始化业务功能（App.init）');
                    app.init(seajs.Module.createRequire(uri));
                // };
                //语言包
                // seajs.use('Fw.loacle', Fw.app && Fw.app.Session ? function(){
                    // Fw.app.Session.load(callback);
                // } : callback);
            });
        }
        else{
            Fw.Logger.error('未定义应用初始化入口（init）');
        }
    },
    /**
     * 定义模块
     * 桥接Seajs
     * http://seajs.org
     */
    define : function() {
        define.apply(this, arguments);
    },
    /**
     * 模版
     * 桥接Juicer
     * http://juicer.name
     */
    template : function() {
        var tpl = arguments[0];
        if(Fw.isArray(tpl)){
            if(tpl.length > 1){
                var arr = [], funs = {};
                //从模版中分出自定义函数
                Fw.each(tpl, function(item){
                    if(Fw.isObject(item)){
                        Fw.apply(funs, item);
                    }
                    else{
                        arr.push(item);
                    }
                });
                //注册自定义函数
                Fw.each(funs, function(prop, fun){
                    if(Fw.isFunction(fun)){
                        juicer.register(prop, fun);
                    }
                });
                //
                arguments[0] = arr.join('');
            }
            else{
                arguments[0] = tpl[0];
            }
        }
        return juicer.apply(this, arguments);
    }
};

//父窗口
if(self != top){
    Fw.TOP_WINDOW = parent.window;
}

//设备判断
var ua = navigator.userAgent.toLowerCase();
Fw.isIPhone = /iphone/i.test(ua);
Fw.isIPad = /ipad/i.test(ua);
Fw.isIOS = Fw.isIPhone || Fw.isIPad;
Fw.isAndroid = /android/i.test(ua);
Fw.isTouch = Fw.isIOS || Fw.isAndroid;

//组件命名空间
Fw.namespace('Fw.core', 'Fw.util');